﻿using System;
using System.Threading;
using System.IO;
using Microsoft.SPOT;

using Gadgeteer.Networking;
using GT = Gadgeteer;
using GTM = Gadgeteer.Modules;
using Gadgeteer.Modules.GHIElectronics;

using GHIElectronics.NETMF.Glide;
using GHIElectronics.NETMF.Glide.Display;
using GHIElectronics.NETMF.Glide.UI;


namespace Tyrannt
{
    public partial class Program
    {
        string[] textDisplay = new string[24];
        uint row = 0;

        GT.StorageDevice storageDev;

        // This will hold the main window.
        Window mainMenuWindow;
        Window characterSelectWindow;
        Window characterGenWindow;
        Window portraitSelectWindow;
        Window classSelectWindow;
        Window mainGameWindow;
        Window sdcardWindow;
        Window placeholderWindow;

        Maze maze;

        const string imagePath = @"\tyrannt\images";
        const string portraitPath = @"\tyrannt\images\portraits";
        const string descriptionPath = @"\tyrannt\descriptions";
        const string charactersPath = @"tyrannt\characters";
        const string mazePath = @"tyrannt\maps";

        Character[] characters = new Character[7];
        int currentCharacter = 1;

        bool sdcardPresent = true;

        Random rand;

        // This method is run when the mainboard is powered up or reset.   
        void ProgramStarted()
        {
            /*******************************************************************************************
            Modules added in the Program.gadgeteer designer view are used by typing 
            their name followed by a period, e.g.  button.  or  camera.
            
            Many modules generate useful events. Type +=<tab><tab> to add a handler to an event, e.g.:
                button.ButtonPressed +=<tab><tab>
            
            If you want to do something periodically, use a GT.Timer and handle its Tick event, e.g.:
                GT.Timer timer = new GT.Timer(1000); // every second (1000ms)
                timer.Tick +=<tab><tab>
                timer.Start();
            *******************************************************************************************/

            // Load the windows
            mainMenuWindow = GlideLoader.LoadWindow(Resources.GetString(Resources.StringResources.MainMenuWindow));
            characterGenWindow = GlideLoader.LoadWindow(Resources.GetString(Resources.StringResources.characterGenWindow));
            sdcardWindow = GlideLoader.LoadWindow(Resources.GetString(Resources.StringResources.sdcardWindow));
            portraitSelectWindow = GlideLoader.LoadWindow(Resources.GetString(Resources.StringResources.portraitSelectWindow));
            classSelectWindow = GlideLoader.LoadWindow(Resources.GetString(Resources.StringResources.classSelectWindow));
            characterSelectWindow = GlideLoader.LoadWindow(Resources.GetString(Resources.StringResources.characterSelectWindow));
            mainGameWindow = GlideLoader.LoadWindow(Resources.GetString(Resources.StringResources.mainGameWindow));

            // Activate touch
            GlideTouch.Initialize();

            InitialiseSDStorage();
            // Initialize the window.
            InitWin();
            InitSD();
            InitSettings();
            InitCharacters();

            // Assigning a window to MainWindow flushes it to the screen.
            // This also starts event handling on the window.
            Glide.MainWindow = mainMenuWindow;
        }

        #region Main Menu Window

        void charactersMenuButton_TapEvent(object sender)
        {
            InitCharacterSelectWindow();
        }

        void playGameButton_TapEvent(object sender)
        {
            InitMainGameWindow();
        }

        #endregion

        #region Character Select Window

        void InitCharacterSelectWindow()
        {
            Button actionButton;
            TextBlock nameTextBlock;
            TextBlock descriptionTextBlock;
            // Character 1
            for (int lp = 1; lp <= 6; lp++)
            {
                string chr = "chr" + lp.ToString();
                string actButtonChild = chr + "ActionButton";
                string nameChild = chr + "NameText";
                string detailsChild = chr + "DetailsText";
                Character currChar = characters[lp];
                actionButton = (Button)characterSelectWindow.GetChildByName(actButtonChild);
                nameTextBlock = (TextBlock)characterSelectWindow.GetChildByName(nameChild);
                descriptionTextBlock = (TextBlock)characterSelectWindow.GetChildByName(detailsChild);
                if (currChar.strength.Current == 0)
                {
                    actionButton.Text = "Roll";
                    nameTextBlock.Text = "Click Roll to";
                    descriptionTextBlock.Text = "Generate Character";
                }
                else
                {
                    actionButton.Text = "Edit";
                    nameTextBlock.Text = currChar.name;
                    descriptionTextBlock.Text = CapString(currChar.race) + " " + CapString(currChar.mobClass);
                }
            }

            Glide.MainWindow = characterSelectWindow;
        }

        void chrActionButton_TapEvent(object sender)
        {
            Button actionButton = (Button)sender;
            switch (actionButton.Name)
            {
                case "chr1ActionButton":
                    currentCharacter = 1;
                    break;
                case "chr2ActionButton":
                    currentCharacter = 2;
                    break;
                case "chr3ActionButton":
                    currentCharacter = 3;
                    break;
                case "chr4ActionButton":
                    currentCharacter = 4;
                    break;
                case "chr5ActionButton":
                    currentCharacter = 5;
                    break;
                case "chr6ActionButton":
                    currentCharacter = 6;
                    break;
                default:
                    FatalError(actionButton.Name + " button name is not recognised");
                    break;
            }

            InitCharacterGenWindow();
        }

        void returnButton_TapEvent(object sender)
        {
            Glide.MainWindow = mainMenuWindow;
        }

        #endregion

        #region Character Generator Window

        void InitCharacterGenWindow()
        {
            // get the current character
            Character currChar = characters[currentCharacter];

            // Get the name Text Box
            TextBox nameTextBox = (TextBox)characterGenWindow.GetChildByName("nameTextBox");
            // Get the races
            RadioButton humanRadio = (RadioButton)characterGenWindow.GetChildByName("humanRadioButton");
            RadioButton dwarfRadio = (RadioButton)characterGenWindow.GetChildByName("dwarfRadioButton");
            RadioButton elfRadio = (RadioButton)characterGenWindow.GetChildByName("elfRadioButton");
            RadioButton gnomeRadio = (RadioButton)characterGenWindow.GetChildByName("gnomeRadioButton");
            // Get the sexs
            RadioButton maleRadio = (RadioButton)characterGenWindow.GetChildByName("maleRadioButton");
            RadioButton femaleRadio = (RadioButton)characterGenWindow.GetChildByName("femaleRadioButton");
            // Get the stats
            TextBlock strTextBlock = (TextBlock)characterGenWindow.GetChildByName("strValue");
            TextBlock intTextBlock = (TextBlock)characterGenWindow.GetChildByName("intValue");
            TextBlock dexTextBlock = (TextBlock)characterGenWindow.GetChildByName("dexValue");

            // Set the Race
            switch (currChar.race.ToLower())
            {
                case "human":
                    humanRadio.Checked = true;
                    dwarfRadio.Checked = false;
                    elfRadio.Checked = false;
                    gnomeRadio.Checked = false;
                    break;
                case "dwarf":
                    humanRadio.Checked = false;
                    dwarfRadio.Checked = true;
                    elfRadio.Checked = false;
                    gnomeRadio.Checked = false;
                    break;
                case "elf":
                    humanRadio.Checked = false;
                    dwarfRadio.Checked = false;
                    elfRadio.Checked = true;
                    gnomeRadio.Checked = false;
                    break;
                case "gnome":
                    humanRadio.Checked = false;
                    dwarfRadio.Checked = false;
                    elfRadio.Checked = false;
                    gnomeRadio.Checked = true;
                    break;
                default:
                    FatalError(currChar.race.ToLower() + " is unknown race");
                    break;
            }

            // Set the Sex
            switch (currChar.sex.ToLower())
            {
                case "male":
                    maleRadio.Checked = true;
                    femaleRadio.Checked = false;
                    break;
                case "female":
                    maleRadio.Checked = false;
                    femaleRadio.Checked = true;
                    break;
                default:
                    FatalError(currChar.sex.ToLower() + " is unknown sex");
                    break;
            }

            // Set the name
            nameTextBox.Text = currChar.name;

            // Set the stats
            strTextBlock.Text = currChar.strength.Current.ToString();
            intTextBlock.Text = currChar.intelligence.Current.ToString();
            dexTextBlock.Text = currChar.dexterity.Current.ToString();

            // Refresh the portrait image
            reloadPortrait();

            // Display the character generator page
            Glide.MainWindow = characterGenWindow;
        }

        void resetPortrait()
        {
            characters[currentCharacter].portrait = 0;
            reloadPortrait();
        }

        private void reloadPortrait()
        {
            string imgPath = portraitPath
                + @"\" + characters[currentCharacter].race
                + @"\" + characters[currentCharacter].sex
                + @"\" + characters[currentCharacter].portrait.ToString() + ".bmp";
            // Get portrait image
            Image portraitImage = (Image)characterGenWindow.GetChildByName("portraitImage");
            try
            {
                portraitImage.Bitmap = storageDev.LoadBitmap(imgPath, Bitmap.BitmapImageType.Bmp);
            }
            catch (Exception e)
            {
                FatalError(e.Message);
            }

            Glide.MainWindow = characterGenWindow;
        }

        void sexRadio_TapEvent(object sender)
        {
            characters[currentCharacter].sex = RadioButtonManager.GetValue("sexRadioButtonGroup");
            resetPortrait();
        }

        void raceRadio_TapEvent(object sender)
        {
            characters[currentCharacter].race = RadioButtonManager.GetValue("raceRadioButtonGroup");
            resetPortrait();
        }

        void rollButton_TapEvent(object sender)
        {
            TextBlock strValueTextBlock = (TextBlock)characterGenWindow.GetChildByName("strValue");
            TextBlock intValueTextBlock = (TextBlock)characterGenWindow.GetChildByName("intValue");
            TextBlock dexValueTextBlock = (TextBlock)characterGenWindow.GetChildByName("dexValue");
            characters[currentCharacter].strength = new MobAttribute(3, 24, RollDice(3, 6));
            characters[currentCharacter].intelligence = new MobAttribute(3, 24, RollDice(3, 6));
            characters[currentCharacter].dexterity = new MobAttribute(3, 24, RollDice(3, 6));
            strValueTextBlock.Text = characters[currentCharacter].strength.Current.ToString();
            intValueTextBlock.Text = characters[currentCharacter].intelligence.Current.ToString();
            dexValueTextBlock.Text = characters[currentCharacter].dexterity.Current.ToString();
            Glide.MainWindow = characterGenWindow;
        }

        void nameTextBox_ValueChangedEvent(object sender)
        {
            TextBox nameTextBox = (TextBox)characterGenWindow.GetChildByName("nameTextBox");
            characters[currentCharacter].name = nameTextBox.Text;
        }

        void portraitImage_TapEvent(object sender)
        {
            LoadPortraits();
            Glide.MainWindow = portraitSelectWindow;
        }

        #endregion

        #region Portrait Select Window

        private void LoadPortraits()
        {
            // Portraits
            Image portraitImage1 = (Image)portraitSelectWindow.GetChildByName("1");
            Image portraitImage2 = (Image)portraitSelectWindow.GetChildByName("2");
            Image portraitImage3 = (Image)portraitSelectWindow.GetChildByName("3");
            Image portraitImage4 = (Image)portraitSelectWindow.GetChildByName("4");
            Image portraitImage5 = (Image)portraitSelectWindow.GetChildByName("5");
            Image portraitImage6 = (Image)portraitSelectWindow.GetChildByName("6");
            string imgPath = portraitPath
                + @"\" + characters[currentCharacter].race
                + @"\" + characters[currentCharacter].sex + @"\";
            try
            {
                portraitImage1.Bitmap = storageDev.LoadBitmap(imgPath + @"1.bmp", Bitmap.BitmapImageType.Bmp);
                portraitImage2.Bitmap = storageDev.LoadBitmap(imgPath + @"2.bmp", Bitmap.BitmapImageType.Bmp);
                portraitImage3.Bitmap = storageDev.LoadBitmap(imgPath + @"3.bmp", Bitmap.BitmapImageType.Bmp);
                portraitImage4.Bitmap = storageDev.LoadBitmap(imgPath + @"4.bmp", Bitmap.BitmapImageType.Bmp);
                portraitImage5.Bitmap = storageDev.LoadBitmap(imgPath + @"5.bmp", Bitmap.BitmapImageType.Bmp);
                portraitImage6.Bitmap = storageDev.LoadBitmap(imgPath + @"6.bmp", Bitmap.BitmapImageType.Bmp);
            }
            catch (Exception e)
            {
                AddError("Fatal Error: " + e.Message);
                Thread.Sleep(Timeout.Infinite);
            }
        }

        void portraitImg_TapEvent(object sender)
        {
            Image selected = (Image)sender;
            characters[currentCharacter].portrait = int.Parse(selected.Name);

            // Load the correct image and reset back to character generator screen
            reloadPortrait();
        }
        #endregion

        #region Class Select Window

        void classSaveButton_TapEvent(object sender)
        {
            SaveCharacter(currentCharacter);
            InitCharacterSelectWindow();
        }

        void classBackButton_TapEvent(object sender)
        {
            Glide.MainWindow = characterGenWindow;
        }

        void classRadio_TapEvent(object sender)
        {
            characters[currentCharacter].mobClass = RadioButtonManager.GetValue("classRadioButtonGroup");
            resetClassDescription();
        }

        void resetClassDescription()
        {
            string descPath = descriptionPath
                           + @"\classes"
                           + @"\" + characters[currentCharacter].mobClass + ".txt";
            // get description text block
            TextBlock descriptionTextBlock = (TextBlock)classSelectWindow.GetChildByName("descriptionTextBlock");

            string desc = ReadTextFile(descPath);
            descriptionTextBlock.Text = desc;
            Glide.MainWindow = classSelectWindow;
        }

        void classButton_TapEvent(object sender)
        {
            // TODO add checks to make sure the dice have rolled and a name entered

            // get the current character
            Character currChar = characters[currentCharacter];

            // Get the radio buttons
            RadioButton warriorRadio = (RadioButton)classSelectWindow.GetChildByName("warriorRadioButton");
            RadioButton mageRadio = (RadioButton)classSelectWindow.GetChildByName("mageRadioButton");
            RadioButton thiefRadio = (RadioButton)classSelectWindow.GetChildByName("thiefRadioButton");
            RadioButton priestRadio = (RadioButton)classSelectWindow.GetChildByName("priestRadioButton");

            // set the class radio button
            switch (currChar.mobClass)
            {
                case "warrior":
                    warriorRadio.Checked = true;
                    mageRadio.Checked = false;
                    thiefRadio.Checked = false;
                    priestRadio.Checked = false;
                    break;
                case "mage":
                    warriorRadio.Checked = false;
                    mageRadio.Checked = true;
                    thiefRadio.Checked = false;
                    priestRadio.Checked = false;
                    break;
                case "thief":
                    warriorRadio.Checked = false;
                    mageRadio.Checked = false;
                    thiefRadio.Checked = true;
                    priestRadio.Checked = false;
                    break;
                case "priest":
                    warriorRadio.Checked = false;
                    mageRadio.Checked = false;
                    thiefRadio.Checked = false;
                    priestRadio.Checked = true;
                    break;
                default:
                    FatalError(currChar.mobClass + " Is an unknown class");
                    break;
            }

            // update the descripton
            resetClassDescription();

            // Display the class select window.
            Glide.MainWindow = classSelectWindow;
        }

        #endregion

        #region Main Game Window

        void InitMainGameWindow()
        {
            try
            {
                maze = new Maze(storageDev, mazePath, 0);
            }
            catch (Exception e)
            {
                FatalError(e.Message);
            }

            RedrawMazeView();
        }

        private void RedrawMazeView()
        {
            Image gameView = (Image)mainGameWindow.GetChildByName("gameImage");
            TextBlock messageTextBlock = (TextBlock)mainGameWindow.GetChildByName("gameTextBlock");
            gameView.Bitmap = maze.View;
            messageTextBlock.Text = maze.Segment;
            Glide.MainWindow = mainGameWindow;
        }

        void gameTextBlock_TapEvent(object sender)
        {
            throw new NotImplementedException();
        }

        void gamePortraitImage_TapEvent(object sender)
        {
            throw new NotImplementedException();
        }

        void rightTextBlock_TapEvent(object sender)
        {
            maze.TurnRight();
            RedrawMazeView();
        }

        void leftTextBlock_TapEvent(object sender)
        {
            maze.TurnLeft();
            RedrawMazeView();
        }

        void forwardTextBlock_TapEvent(object sender)
        {
            maze.MoveForward();
            RedrawMazeView();
        }
        #endregion

        #region Core Routines

        void InitCharacters()
        {
            for (int lp = 1; lp <= 6; lp++)
            {
                string fname = charactersPath + @"\" + lp.ToString() + ".bin";
                if (FileExists(fname))
                {
                    characters[lp] = LoadCharacter(lp);
                }
                else
                {
                    SaveCharacter(lp);
                }
            }
        }

        Character LoadCharacter(int lp)
        {
            string fname = charactersPath + @"\" + lp.ToString() + ".bin";
            Character newCharacter = new Character();
            try
            {
                byte[] rawCharacter = storageDev.ReadFile(fname);
                newCharacter = (Character)Reflection.Deserialize(rawCharacter, typeof(Character));
            }
            catch (Exception e)
            {
                FatalError(e.Message);
            }
            return newCharacter;
        }

        private void SaveCharacter(int lp)
        {
            string fname = charactersPath + @"\" + lp.ToString() + ".bin";
            byte[] rawCharacter = Reflection.Serialize(characters[lp], typeof(Character));
            try
            {
                storageDev.WriteFile(fname, rawCharacter);
                storageDev.Volume.FlushAll();
            }
            catch (Exception e)
            {
                FatalError(e.Message);
            }
        }

        bool FileExists(string filePath)
        {
            bool exists = false;
            try
            {
                FileStream dummy = storageDev.OpenRead(filePath);
                dummy.Close();
                exists = true;
            }
            catch (IOException e)
            {
                if (e.ErrorCode == IOException.IOExceptionErrorCode.FileNotFound)
                {
                    exists = false;
                }
                else
                {
                    FatalError(e.Message);
                }
            }
            return exists;
        }

        private void InitSettings()
        {
            for (int lp = 1; lp <= 6; lp++)
                characters[lp] = new Character();

            rand = new Random(DateTime.Now.Second);
        }

        private void InitSD()
        {
            sdCard.SDCardUnmounted += new SDCard.SDCardUnmountedEventHandler(sdCard_SDCardUnmounted);
            sdCard.SDCardMounted += new SDCard.SDCardMountedEventHandler(sdCard_SDCardMounted);
        }

        void sdCard_SDCardMounted(SDCard sender, GT.StorageDevice SDCard)
        {
            if (sdcardPresent == false)
            {
                Glide.MainWindow = placeholderWindow;
                sdcardPresent = true;
            }
        }

        void sdCard_SDCardUnmounted(SDCard sender)
        {
            placeholderWindow = Glide.MainWindow;
            Glide.MainWindow = sdcardWindow;
            sdcardPresent = false;
        }

        void InitWin()
        {

            Image logoImage = (Image)mainMenuWindow.GetChildByName("logoImage");
            string logoPath = imagePath + @"\logo.gif";

            #region Main Menu

            try
            {
                logoImage.Bitmap = storageDev.LoadBitmap(logoPath, Bitmap.BitmapImageType.Gif);
            }
            catch (Exception e)
            {
                FatalError(e.Message);
            }

            Button playGameButton = (Button)mainMenuWindow.GetChildByName("playMenuButton");
            Button charactersMenuButton = (Button)mainMenuWindow.GetChildByName("charactersMenuButton");
            Button creatorMenuButton = (Button)mainMenuWindow.GetChildByName("creatorMenuButton");
            playGameButton.TapEvent += new OnTap(playGameButton_TapEvent);
            charactersMenuButton.TapEvent += new OnTap(charactersMenuButton_TapEvent);

            #endregion

            #region Character Selector

            // Main menu button
            Button returnButton = (Button)characterSelectWindow.GetChildByName("returnButton");
            returnButton.TapEvent += new OnTap(returnButton_TapEvent);
            // Roll/Edit buttons for each character
            Button chr1ActionButton = (Button)characterSelectWindow.GetChildByName("chr1ActionButton");
            Button chr2ActionButton = (Button)characterSelectWindow.GetChildByName("chr2ActionButton");
            Button chr3ActionButton = (Button)characterSelectWindow.GetChildByName("chr3ActionButton");
            Button chr4ActionButton = (Button)characterSelectWindow.GetChildByName("chr4ActionButton");
            Button chr5ActionButton = (Button)characterSelectWindow.GetChildByName("chr5ActionButton");
            Button chr6ActionButton = (Button)characterSelectWindow.GetChildByName("chr6ActionButton");
            chr1ActionButton.TapEvent += new OnTap(chrActionButton_TapEvent);
            chr2ActionButton.TapEvent += new OnTap(chrActionButton_TapEvent);
            chr3ActionButton.TapEvent += new OnTap(chrActionButton_TapEvent);
            chr4ActionButton.TapEvent += new OnTap(chrActionButton_TapEvent);
            chr5ActionButton.TapEvent += new OnTap(chrActionButton_TapEvent);
            chr6ActionButton.TapEvent += new OnTap(chrActionButton_TapEvent);

            #endregion

            #region Character Generator
            // Get the TextBox
            TextBox nameTextBox = (TextBox)characterGenWindow.GetChildByName("nameTextBox");
            // Get the Buttons
            Button rollButton = (Button)characterGenWindow.GetChildByName("rollButton");
            Button classButton = (Button)characterGenWindow.GetChildByName("classButton");
            // Get portrait image
            Image portraitImage = (Image)characterGenWindow.GetChildByName("portraitImage");
            // Get the races
            RadioButton humanRadio = (RadioButton)characterGenWindow.GetChildByName("humanRadioButton");
            RadioButton dwarfRadio = (RadioButton)characterGenWindow.GetChildByName("dwarfRadioButton");
            RadioButton elfRadio = (RadioButton)characterGenWindow.GetChildByName("elfRadioButton");
            RadioButton gnomeRadio = (RadioButton)characterGenWindow.GetChildByName("gnomeRadioButton");
            // Get the sex's
            RadioButton maleRadio = (RadioButton)characterGenWindow.GetChildByName("maleRadioButton");
            RadioButton femaleRadio = (RadioButton)characterGenWindow.GetChildByName("femaleRadioButton");


            // Add a tap event handler to open the keyboard.
            nameTextBox.TapEvent += new OnTap(Glide.OpenKeyboard);
            // Add a tap event for the roll and class button
            rollButton.TapEvent += new OnTap(rollButton_TapEvent);
            classButton.TapEvent += new OnTap(classButton_TapEvent);
            // Add a tap event for the portrait image
            portraitImage.TapEvent += new OnTap(portraitImage_TapEvent);
            // add a tap event for all the Race radio buttons (To the same event handler)
            humanRadio.TapEvent += new OnTap(raceRadio_TapEvent);
            dwarfRadio.TapEvent += new OnTap(raceRadio_TapEvent);
            elfRadio.TapEvent += new OnTap(raceRadio_TapEvent);
            gnomeRadio.TapEvent += new OnTap(raceRadio_TapEvent);
            // add a tap event for all the sex's radion buttons (To the same event handler)
            maleRadio.TapEvent += new OnTap(sexRadio_TapEvent);
            femaleRadio.TapEvent += new OnTap(sexRadio_TapEvent);

            // Add a value changed handler.
            nameTextBox.ValueChangedEvent += new OnValueChanged(nameTextBox_ValueChangedEvent);
            #endregion

            #region Portrait Picker
            // Portraits

            for (int lp = 1; lp <= 6; lp++)
            {
                Image tmpPortraitImage = (Image)portraitSelectWindow.GetChildByName(lp.ToString());
                tmpPortraitImage.TapEvent += new OnTap(portraitImg_TapEvent);
            }
            #endregion

            #region Class Picker

            // Get the radio buttons
            RadioButton warriorRadio = (RadioButton)classSelectWindow.GetChildByName("warriorRadioButton");
            RadioButton mageRadio = (RadioButton)classSelectWindow.GetChildByName("mageRadioButton");
            RadioButton thiefRadio = (RadioButton)classSelectWindow.GetChildByName("thiefRadioButton");
            RadioButton priestRadio = (RadioButton)classSelectWindow.GetChildByName("priestRadioButton");
            // get the buttons
            Button classBackButton = (Button)classSelectWindow.GetChildByName("backButton");
            Button classSaveButton = (Button)classSelectWindow.GetChildByName("saveButton");

            // setup the tap event handlers for the radio buttons (Using same handling routine)
            warriorRadio.TapEvent += new OnTap(classRadio_TapEvent);
            mageRadio.TapEvent += new OnTap(classRadio_TapEvent);
            thiefRadio.TapEvent += new OnTap(classRadio_TapEvent);
            priestRadio.TapEvent += new OnTap(classRadio_TapEvent);
            // setup tap event handlers for the buttons
            classBackButton.TapEvent += new OnTap(classBackButton_TapEvent);
            classSaveButton.TapEvent += new OnTap(classSaveButton_TapEvent);

            #endregion

            #region Main Game

            // portrait images
            for (int lp = 1; lp <= 6; lp++)
            {
                string imgName = "portrait" + lp.ToString() + "Image";
                Image tmpPortraitImage = (Image)mainGameWindow.GetChildByName(imgName);
                tmpPortraitImage.TapEvent += new OnTap(gamePortraitImage_TapEvent);
            }
            // movement text blocks
            TextBlock forwardTextBlock = (TextBlock)mainGameWindow.GetChildByName("forwardTextBlock");
            TextBlock leftTextBlock = (TextBlock)mainGameWindow.GetChildByName("leftTextBlock");
            TextBlock rightTextBlock = (TextBlock)mainGameWindow.GetChildByName("rightTextBlock");
            forwardTextBlock.TapEvent += new OnTap(forwardTextBlock_TapEvent);
            leftTextBlock.TapEvent += new OnTap(leftTextBlock_TapEvent);
            rightTextBlock.TapEvent += new OnTap(rightTextBlock_TapEvent);

            // text Block
            TextBlock gameTextBlock = (TextBlock)mainGameWindow.GetChildByName("gameTextBlock");
            gameTextBlock.TapEvent += new OnTap(gameTextBlock_TapEvent);

            #endregion

        }

        string CapString(string s)
        {
            // Return char and concat substring.
            return s.Substring(0, 1).ToUpper() + s.Substring(1);
        }

        string ReadTextFile(string path)
        {
            string result = "";
            try
            {
                byte[] rawBytes = storageDev.ReadFile(path);
                char[] rawCharacters = System.Text.UTF8Encoding.UTF8.GetChars(rawBytes);
                result = new string(rawCharacters);
            }
            catch (Exception e)
            {
                FatalError(e.Message);
            }
            return result;
        }

        private void InitialiseSDStorage()
        {
            if (sdCard.IsCardInserted == false)
            {
                placeholderWindow = Glide.MainWindow;
                Glide.MainWindow = sdcardWindow;
                sdcardPresent = false;
                while (sdCard.IsCardInserted == false)
                    Thread.Sleep(500);
            }
            Debug.Print("Card is inserted.");

            if (sdCard.IsCardMounted == false)
            {
                Debug.Print("Mounting SD card");
                sdCard.MountSDCard();
            }

            if (sdCard.IsCardMounted == false)
            {
                Debug.Print("Fatal Error - Cannot mount SD Card");
                Thread.Sleep(Timeout.Infinite);
            }
            Debug.Print("SD Card Mounted");
            Debug.Print(" ");

            storageDev = sdCard.GetStorageDevice();
        }

        void FatalError(string msg)
        {
            AddError("FATAL ERROR:");
            AddError(msg);
            Thread.Sleep(Timeout.Infinite);
        }

        void AddError(string msg)
        {
            msg = "!" + msg;
            AddText(msg);
        }

        void AddText(string msg)
        {
            if (row >= 23)
            {
                for (uint lp = 0; lp <= 22; lp++)
                {
                    DrawTextLine(textDisplay[lp], lp, true);
                    textDisplay[lp] = textDisplay[lp + 1];
                    DrawTextLine(textDisplay[lp], lp, false);
                }
                DrawTextLine(textDisplay[23], 22, true);
                textDisplay[23] = msg;
                DrawTextLine(msg, 22, false);
            }
            else
            {
                textDisplay[row] = msg;
                DrawTextLine(msg, row, false);
                row++;
            }
        }

        void DrawTextLine(string msg, uint line, bool erase)
        {
            if (msg == "")
                msg = " ";
            bool error = false;
            if (msg.Substring(0, 1) == "!")
            {
                error = true;
                msg = msg.Substring(1);
            }
            GT.Color colour;
            if (erase == true)
                colour = GT.Color.Black;
            else
            {
                if (error == true)
                    colour = GT.Color.Red;
                else
                    colour = GT.Color.Yellow;
            }

            DrawTextLine(msg, line, colour);
        }

        void DrawTextLine(string msg, uint line, GT.Color colour)
        {
            display.SimpleGraphics.DisplayText(msg, Resources.GetFont(Resources.FontResources.small), colour, 0, (line * 10));
        }

        int RollDice(int numDice, int sides)
        {
            int total = 0;
            for (int lp = 1; lp <= numDice; lp++)
            {
                total = total + rand.Next(sides) + 1;
            }
            return total;
        }

        #endregion

    }
}
